<!DOCTYPE html>
<html  lang="zh">
<head>
    <meta charset="utf-8" />

<meta name="generator" content="Hexo 3.8.0" />

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />

<title>【iOS 开发】使用环信实现聊天遇到的一些坑 - OBJC.VIP</title>


    <meta name="description" content="使用环信实现聊天的过程遇到了一些坑，记录一下避免自己和其他人踩坑或者尽快出坑。">
<meta name="keywords" content="iOS 开发,环信">
<meta property="og:type" content="article">
<meta property="og:title" content="【iOS 开发】使用环信实现聊天遇到的一些坑">
<meta property="og:url" content="https://objcvip.github.io/imeasemob/index.html">
<meta property="og:site_name" content="OBJC.VIP">
<meta property="og:description" content="使用环信实现聊天的过程遇到了一些坑，记录一下避免自己和其他人踩坑或者尽快出坑。">
<meta property="og:locale" content="zh-CN">
<meta property="og:image" content="https://objcvip.github.io/images/og_image.png">
<meta property="og:updated_time" content="2019-09-08T08:45:15.220Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="【iOS 开发】使用环信实现聊天遇到的一些坑">
<meta name="twitter:description" content="使用环信实现聊天的过程遇到了一些坑，记录一下避免自己和其他人踩坑或者尽快出坑。">
<meta name="twitter:image" content="https://objcvip.github.io/images/og_image.png">







<link rel="icon" href="/images/favicon.svg">


<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.7.2/css/bulma.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.1/css/all.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:400,600|Source+Code+Pro">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@9.12.0/styles/atom-one-dark.css">


    
    
    
    <style>body>.footer,body>.navbar,body>.section{opacity:0}</style>
    

    
    
    
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/lightgallery@1.6.8/dist/css/lightgallery.min.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/justifiedGallery@3.7.0/dist/css/justifiedGallery.min.css">
    

    
    

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/outdatedbrowser@1.1.5/outdatedbrowser/outdatedbrowser.min.css">


    
    
    
    

<link rel="stylesheet" href="/css/back-to-top.css">


    
    

    
    
    
    

    
    
<link rel="stylesheet" href="/css/progressbar.css">
<script src="https://cdn.jsdelivr.net/npm/pace-js@1.0.2/pace.min.js"></script>

    
    
    


<link rel="stylesheet" href="/css/style.css">
</head>
<body class="is-1-column">
    <nav class="navbar navbar-main">
    <div class="container">
        <div class="navbar-brand is-flex-center">
            <a class="navbar-item navbar-logo" href="/">
            
                <img src="/images/logo.svg" alt="【iOS 开发】使用环信实现聊天遇到的一些坑" height="28">
            
            </a>
        </div>
        <div class="navbar-menu">
            
            <div class="navbar-start">
                
                <a class="navbar-item"
                href="/">首页</a>
                
                <a class="navbar-item"
                href="/archives">归档</a>
                
                <a class="navbar-item"
                href="/categories">分类</a>
                
                <a class="navbar-item"
                href="/tags">标签</a>
                
                <a class="navbar-item"
                href="/links">友链</a>
                
                <a class="navbar-item"
                href="/about">关于</a>
                
            </div>
            
            <div class="navbar-end">
                
                
                
                <a class="navbar-item search" title="搜索" href="javascript:;">
                    <i class="fas fa-search"></i>
                </a>
                
            </div>
        </div>
    </div>
</nav>
    
    <section class="section">
        <div class="container">
            <div class="columns">
                <div class="column is-12 has-order-2 column-main"><div class="card">
    
    <div class="card-content article ">
        
        <div class="level article-meta is-size-7 is-uppercase is-mobile is-overflow-x-auto">
            <div class="level-left">
                <time class="level-item has-text-grey" datetime="2019-08-26T07:47:00.000Z">2019-08-26</time>
                
                <div class="level-item">
                <a class="has-link-grey -link" href="/categories/iOS-开发/">iOS 开发</a>
                </div>
                
                
                <span class="level-item has-text-grey">
                    
                    
                    11 分钟 读完 (大约 1677 个字)
                </span>
                
                
            </div>
        </div>
        
        <h1 class="title is-size-3 is-size-4-mobile has-text-weight-normal">
            
                【iOS 开发】使用环信实现聊天遇到的一些坑
            
        </h1>
        <div class="content">
            <p>使用环信实现聊天的过程遇到了一些坑，记录一下避免自己和其他人踩坑或者尽快出坑。<br><a id="more"></a></p>
<h2 id="问题1-聊天页面环信工具栏向上偏移"><a href="#问题1-聊天页面环信工具栏向上偏移" class="headerlink" title="问题1 聊天页面环信工具栏向上偏移"></a>问题1 聊天页面环信工具栏向上偏移</h2><h3 id="问题描述："><a href="#问题描述：" class="headerlink" title="问题描述："></a>问题描述：</h3><p>在聊天页面，点击输入框弹起键盘，点击<code>IQKeyboardManager</code>带的完成按钮或者点击空白页面收起键盘，反复操作多次后，会出现页面向上偏移，环信<code>UI</code>的工具栏移动到了页面最上边。</p>
<h3 id="解决方案："><a href="#解决方案：" class="headerlink" title="解决方案："></a>解决方案：</h3><p>在聊天页面禁用<code>IQKeyboardManager</code>。<br><figure class="highlight objc hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">- (<span class="hljs-keyword">void</span>)viewDidAppear:(<span class="hljs-built_in">BOOL</span>)animated</span><br><span class="line">&#123;</span><br><span class="line">    [<span class="hljs-keyword">super</span> viewDidAppear:animated];</span><br><span class="line">    IQKeyboardManager *keyboardManager =  [IQKeyboardManager sharedManager];</span><br><span class="line">    keyboardManager.enable = <span class="hljs-literal">NO</span>;</span><br><span class="line">    keyboardManager.enableAutoToolbar = <span class="hljs-literal">NO</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">- (<span class="hljs-keyword">void</span>)viewWillDisappear:(<span class="hljs-built_in">BOOL</span>)animated</span><br><span class="line">&#123;</span><br><span class="line">    [<span class="hljs-keyword">super</span> viewWillDisappear:animated];</span><br><span class="line">    IQKeyboardManager *keyboardManager =  [IQKeyboardManager sharedManager];</span><br><span class="line">    keyboardManager.enable = <span class="hljs-literal">YES</span>;</span><br><span class="line">    keyboardManager.enableAutoToolbar = <span class="hljs-literal">YES</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h2 id="问题2-保存环信昵称头像到数据库失败"><a href="#问题2-保存环信昵称头像到数据库失败" class="headerlink" title="问题2 保存环信昵称头像到数据库失败"></a>问题2 保存环信昵称头像到数据库失败</h2><h3 id="问题描述：-1"><a href="#问题描述：-1" class="headerlink" title="问题描述："></a>问题描述：</h3><p>环信服务器不存储用户的昵称头像等用户数据。需要客户端自己来存储并展示在界面上。有几个时机是需要插入或更新一条包含昵称、头像的用户数据到数据库里，比如查看用户详情，在某个页面收到环信消息。我们服务器提供的查询用户信息接口返回的昵称和头像，之前是没有问题的，有一次出现了从用户信息界面进入聊天页面不显示昵称的问题。</p>
<h3 id="问题原因："><a href="#问题原因：" class="headerlink" title="问题原因："></a>问题原因：</h3><p>经排查，接口返回的用户头像字段的值是<code>null</code>，由于客户端之前没有做空处理，导致插入或更新一条数据失败。<br><figure class="highlight plain hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">DB Query: INSERT or REPLACE INTO t_huanxin (hxId,nickname,avatar) VALUES (?,?,?)</span><br><span class="line">Unknown error finalizing or resetting statement (19: NOT NULL constraint failed: t_huanxin.avatar)</span><br></pre></td></tr></table></figure></p>
<h3 id="解决方案：-1"><a href="#解决方案：-1" class="headerlink" title="解决方案："></a>解决方案：</h3><p>存储用户信息到本地数据库时增加安全判断。如果为空，就存入空字符串。避免插入或更新字段为<code>null</code>导致操作失败。<br><figure class="highlight objc hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-built_in">NSString</span> *nickname = dic[<span class="hljs-string">@"nickname"</span>]?:<span class="hljs-string">@""</span>;</span><br><span class="line"><span class="hljs-built_in">NSString</span> *avatar = dic[<span class="hljs-string">@"avatar"</span>]?:<span class="hljs-string">@""</span>;</span><br></pre></td></tr></table></figure></p>
<h2 id="问题3-聊天页面发送首条消息后下拉刷新出现两条重复消息"><a href="#问题3-聊天页面发送首条消息后下拉刷新出现两条重复消息" class="headerlink" title="问题3 聊天页面发送首条消息后下拉刷新出现两条重复消息"></a>问题3 聊天页面发送首条消息后下拉刷新出现两条重复消息</h2><h3 id="问题描述：-2"><a href="#问题描述：-2" class="headerlink" title="问题描述："></a>问题描述：</h3><p>使用环信<code>Demo</code>发送消息，首条消息发送后，下拉刷新，单聊页面会有两条重复的消息。<br>操作步骤：1.点击单聊页面右上角的清空按钮，清空某个用户的消息。2.返回会话列表。3.首次进入该用户的单聊页面。4.发送首条消息。5.页面下拉刷新。6.出现了两条一摸一样的消息。</p>
<h3 id="解决方案：-2"><a href="#解决方案：-2" class="headerlink" title="解决方案："></a>解决方案：</h3><p>在<code>EMChatViewController</code>的<code>tableViewDidTriggerHeaderRefresh</code>方法中增加如下判断。<br><figure class="highlight objc hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">- (<span class="hljs-keyword">void</span>)tableViewDidTriggerHeaderRefresh</span><br><span class="line">&#123;</span><br><span class="line">    <span class="hljs-comment">//解决首条消息发送后下拉刷新出现两条重复消息的BUG 开始</span></span><br><span class="line">    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">self</span>.dataArray.count &amp;&amp; <span class="hljs-keyword">self</span>.moreMsgId == <span class="hljs-literal">nil</span>) &#123;</span><br><span class="line">        [<span class="hljs-keyword">self</span> tableViewDidFinishTriggerHeader:<span class="hljs-literal">YES</span> reload:<span class="hljs-literal">NO</span>];</span><br><span class="line">        <span class="hljs-keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="hljs-comment">//解决首条消息发送后下拉刷新出现两条重复消息的BUG 结束</span></span><br><span class="line">    other code</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h2 id="问题4-聊天页面发送语音，点击“按住录音”，发送了0秒的聊天记录"><a href="#问题4-聊天页面发送语音，点击“按住录音”，发送了0秒的聊天记录" class="headerlink" title="问题4 聊天页面发送语音，点击“按住录音”，发送了0秒的聊天记录"></a>问题4 聊天页面发送语音，点击“按住录音”，发送了0秒的聊天记录</h2><h3 id="问题描述：-3"><a href="#问题描述：-3" class="headerlink" title="问题描述："></a>问题描述：</h3><p><code>iOS</code>环信<code>Demo</code>聊天页面，发送语音，点击“按住录音”，发送了0秒的聊天记录。</p>
<h3 id="解决方案：-3"><a href="#解决方案：-3" class="headerlink" title="解决方案："></a>解决方案：</h3><p>在<code>EMChatViewController</code>的<code>chatBarRecordAudioViewStopRecord:timeLength:</code>方法中增加对录音时长的判断。<br><figure class="highlight objc hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">- (<span class="hljs-keyword">void</span>)chatBarRecordAudioViewStopRecord:(<span class="hljs-built_in">NSString</span> *)aPath</span><br><span class="line">                              timeLength:(<span class="hljs-built_in">NSInteger</span>)aTimeLength</span><br><span class="line">&#123;</span><br><span class="line">    EMVoiceMessageBody *body = [[EMVoiceMessageBody alloc] initWithLocalPath:aPath displayName:<span class="hljs-string">@"audio"</span>];</span><br><span class="line">    body.duration = (<span class="hljs-keyword">int</span>)aTimeLength;</span><br><span class="line">    <span class="hljs-keyword">if</span> (body.duration == <span class="hljs-number">0</span>) &#123;</span><br><span class="line">        <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"录音时长为0"</span>);</span><br><span class="line">        <span class="hljs-built_in">NSLog</span>(<span class="hljs-string">@"录制时间过短，不能发送"</span>);</span><br><span class="line">        <span class="hljs-keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    [<span class="hljs-keyword">self</span> _sendMessageWithBody:body ext:<span class="hljs-literal">nil</span> isUpload:<span class="hljs-literal">YES</span>];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h2 id="问题5-聊天页面点击查看图片，图片右上角按钮显示Done"><a href="#问题5-聊天页面点击查看图片，图片右上角按钮显示Done" class="headerlink" title="问题5 聊天页面点击查看图片，图片右上角按钮显示Done"></a>问题5 聊天页面点击查看图片，图片右上角按钮显示<code>Done</code></h2><h3 id="问题描述：-4"><a href="#问题描述：-4" class="headerlink" title="问题描述："></a>问题描述：</h3><p>聊天页面，点击查看图片，图片右上角的按钮显示<code>Done</code>，而不是”完成“。</p>
<h3 id="解决方案：-4"><a href="#解决方案：-4" class="headerlink" title="解决方案："></a>解决方案：</h3><p>直接全局搜索<code>Done</code>,把环信<code>UI</code>里的<code>Done</code>,替换成”完成“即可。</p>
<h2 id="问题6-如何实现推送消息内容自定义"><a href="#问题6-如何实现推送消息内容自定义" class="headerlink" title="问题6 如何实现推送消息内容自定义"></a>问题6 如何实现推送消息内容自定义</h2><h3 id="问题描述：-5"><a href="#问题描述：-5" class="headerlink" title="问题描述："></a>问题描述：</h3><p>不想使用环信默认的推送内容：”您有一条新消息”，或”xxx：消息内容”。想实现自定义的消息内容。</p>
<h3 id="解决方案：-5"><a href="#解决方案：-5" class="headerlink" title="解决方案："></a>解决方案：</h3><p>发送消息扩展里添加字段<code>em_apns_ext</code><br><figure class="highlight objc hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">nickname:<span class="hljs-string">"王小二"</span>,</span><br><span class="line">avatar:<span class="hljs-string">"http://www.baidu.com"</span>,</span><br><span class="line">em_apns_ext:&#123;<span class="hljs-string">"em_push_content"</span>:<span class="hljs-string">"自定义推送内容"</span>&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>参考链接：<a href="http://docs-im.easemob.com/im/ios/apns/content" target="_blank" rel="noopener">环信 APNs 内容解析文档</a></p>
<h2 id="问题7-头像链接与路由短链冲突"><a href="#问题7-头像链接与路由短链冲突" class="headerlink" title="问题7 头像链接与路由短链冲突"></a>问题7 头像链接与路由短链冲突</h2><h3 id="问题描述：-6"><a href="#问题描述：-6" class="headerlink" title="问题描述："></a>问题描述：</h3><p>项目里点击推送通知到落地页采用了路由模式，有一个场景是需要我们自己服务器发推送点击通知栏跳转到聊天页面。路由短链类似：<code>page://chat?from=hxId_10086</code>,由于某些原因，需要带上昵称和头像，加上头像链接后，短链变成了<code>page://chat?from=hxId_10086&amp;avatar=http://www.baidu.com&amp;nickname=王小二</code>，<code>iOS</code> 解析短链的方法是先把短链字符串转成了<code>URL</code>，加了<code>avatar</code>参数之后，转换失败，导致无法跳转。</p>
<h3 id="解决方案：-6"><a href="#解决方案：-6" class="headerlink" title="解决方案："></a>解决方案：</h3><ul>
<li>方案1：<br>由于短链中含有<code>URL</code>，其实违反了路由链接设计的初衷，可以把<code>avatar</code>的值用<code>AES</code>加密一下传输，避免出现链接。</li>
<li>方案2：<br>不把短链字符串转换成<code>URL</code>，直接处理短链，去解析。</li>
</ul>
<h2 id="问题8-小程序发的语音消息iOS无法播放"><a href="#问题8-小程序发的语音消息iOS无法播放" class="headerlink" title="问题8 小程序发的语音消息iOS无法播放"></a>问题8 小程序发的语音消息<code>iOS</code>无法播放</h2><h3 id="问题描述：-7"><a href="#问题描述：-7" class="headerlink" title="问题描述："></a>问题描述：</h3><p>小程序发过来的语音消息<code>iOS</code>无法播放。</p>
<h3 id="问题原因：-1"><a href="#问题原因：-1" class="headerlink" title="问题原因："></a>问题原因：</h3><p><code>Android</code>和<code>iOS</code>发的语音格式都是<code>AMR</code>，小程序发的语音格式是<code>MP3</code>，<code>iOS</code>收到音频后，会先调用<code>_convertAudioFile:</code>方法转换格式，该方法内部实现实现里有一行代码是判断路径是否是<code>MP3</code>文件的，<br><figure class="highlight objc hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[EMAudioPlayerHelper isMP3File:retPath]</span><br></pre></td></tr></table></figure></p>
<p>这个判断方法有问题，发过来的是<code>MP3</code>，却判断不是<code>MP3</code>，接着音频被当成<code>AMR</code>去转换<code>WAV</code> ，转换音频格式失败，播放失败。</p>
<h3 id="解决方案：-7"><a href="#解决方案：-7" class="headerlink" title="解决方案："></a>解决方案：</h3><p>在<code>EMAudioPlayerHelper</code>类中的<code>startPlayerWithPath:model:completion:</code>方法中增加判断，如果含有<code>.mp3</code>，就不转换，直接去播放。不含<code>.mp3</code>，就照旧走<code>_convertAudioFile:</code>转换格式方法。<br><figure class="highlight objc hljs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="hljs-keyword">if</span> ([aPath containsString:<span class="hljs-string">@".mp3"</span>]) &#123;</span><br><span class="line">   <span class="hljs-comment">//不转换</span></span><br><span class="line">&#125;<span class="hljs-keyword">else</span> &#123;</span><br><span class="line">   aPath = [<span class="hljs-keyword">self</span> _convertAudioFile:aPath];</span><br><span class="line">&#125;</span><br><span class="line"><span class="hljs-comment">// aPath = [self _convertAudioFile:aPath];</span></span><br></pre></td></tr></table></figure></p>
<h3 id="问题扩展："><a href="#问题扩展：" class="headerlink" title="问题扩展："></a>问题扩展：</h3><p><code>iOS</code>发的语音消息，<code>Web</code>/小程序收到后无法播放？<br><code>App</code>端发来的文件是<code>AMR</code>格式的，小程序需要下载的时候转成<code>MP3</code>格式去播放。转换方法如下：<br>参考链接：<a href="http://docs-im.easemob.com/im/web/basics/message#%E9%9F%B3%E9%A2%91%E6%B6%88%E6%81%AF" target="_blank" rel="noopener">环信 Web IM 音频消息文档</a></p>

        </div>
        
        <div class="level is-size-7 is-uppercase">
            <div class="level-start">
                <div class="level-item">
                    <span class="is-size-6 has-text-grey has-mr-7">#</span>
                    <a class="has-link-grey -link" href="/tags/iOS-开发/">iOS 开发</a>, <a class="has-link-grey -link" href="/tags/环信/">环信</a>
                </div>
            </div>
        </div>
        
        
        
    </div>
</div>





<div class="card card-transparent">
    <div class="level post-navigation is-flex-wrap is-mobile">
        
        <div class="level-start">
            <a class="level level-item has-link-grey  article-nav-prev" href="/面试题讨论9.3/">
                <i class="level-item fas fa-chevron-left"></i>
                <span class="level-item">面试题讨论（2019.09.03）</span>
            </a>
        </div>
        
        
        <div class="level-end">
            <a class="level level-item has-link-grey  article-nav-next" href="/DataStructurePart2/">
                <span class="level-item">《大话数据结构》二</span>
                <i class="level-item fas fa-chevron-right"></i>
            </a>
        </div>
        
    </div>
</div>



<div class="card">
    <div class="card-content">
        <h3 class="title is-5 has-text-weight-normal">评论</h3>
        
<div id="comment-container"></div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gitalk@1.6.0/dist/gitalk.css">
<script src="https://cdn.jsdelivr.net/npm/gitalk@1.6.0/dist/gitalk.min.js"></script>

<script>
    var gitalk = new Gitalk({
        clientID: '7cf9ae5a9ae4228f59ef',
        clientSecret: 'a60824892847d86dab15dae00b18a8227f9af769',
        id: '4c562015cb2da18590f5d91714a998ad',
        repo: 'Comments',
        owner: 'objcvip',
        admin: "objcvip",
        createIssueManually: false,
        distractionFreeMode: true
    })
    gitalk.render('comment-container')
</script>

    </div>
</div>
</div>
                
                
            </div>
        </div>
    </section>
    <footer class="footer">
    <div class="container">
        <div class="level">
            <div class="level-start has-text-centered-mobile">
                <a class="footer-logo is-block has-mb-6" href="/">
                
                    <img src="/images/logo.svg" alt="【iOS 开发】使用环信实现聊天遇到的一些坑" height="28">
                
                </a>
                <p class="is-size-7">
                &copy; 2020 ObjC.vip&nbsp;
                All rights reserved.
                
                </p>
            </div>
            <div class="level-end">
            
            </div>
        </div>
    </div>
</footer>
    <script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment@2.22.2/min/moment-with-locales.min.js"></script>
<script>moment.locale("zh-CN");</script>

<script>
var IcarusThemeSettings = {
    article: {
        highlight: {
            clipboard: true,
            fold: 'unfolded'
        }
    }
};
</script>


    <script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.4/dist/clipboard.min.js" defer></script>



    
    
    
    <script src="/js/animation.js"></script>
    

    
    
    
    <script src="https://cdn.jsdelivr.net/npm/lightgallery@1.6.8/dist/js/lightgallery.min.js" defer></script>
    <script src="https://cdn.jsdelivr.net/npm/justifiedGallery@3.7.0/dist/js/jquery.justifiedGallery.min.js" defer></script>
    <script src="/js/gallery.js" defer></script>
    

    
    

<div id="outdated">
    <h6>Your browser is out-of-date!</h6>
    <p>Update your browser to view this website correctly. <a id="btnUpdateBrowser" href="http://outdatedbrowser.com/">Update
            my browser now </a></p>
    <p class="last"><a href="#" id="btnCloseUpdateBrowser" title="Close">&times;</a></p>
</div>
<script src="https://cdn.jsdelivr.net/npm/outdatedbrowser@1.1.5/outdatedbrowser/outdatedbrowser.min.js" defer></script>
<script>
    document.addEventListener("DOMContentLoaded", function () {
        outdatedBrowser({
            bgColor: '#f25648',
            color: '#ffffff',
            lowerThan: 'flex'
        });
    });
</script>


    
    
<script src="https://cdn.jsdelivr.net/npm/mathjax@2.7.5/unpacked/MathJax.js?config=TeX-MML-AM_CHTML" defer></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
    MathJax.Hub.Config({
        'HTML-CSS': {
            matchFontHeight: false
        },
        SVG: {
            matchFontHeight: false
        },
        CommonHTML: {
            matchFontHeight: false
        },
        tex2jax: {
            inlineMath: [
                ['$','$'],
                ['\\(','\\)']
            ]
        }
    });
});
</script>

    
    

<a id="back-to-top" title="回到顶端" href="javascript:;">
    <i class="fas fa-chevron-up"></i>
</a>
<script src="/js/back-to-top.js" defer></script>


    
    

    
    
    
    

    
    
    
    
    


<script src="/js/main.js" defer></script>

    
    <div class="searchbox ins-search">
    <div class="searchbox-container ins-search-container">
        <div class="searchbox-input-wrapper">
            <input type="text" class="searchbox-input ins-search-input" placeholder="想要查找什么..." />
            <span class="searchbox-close ins-close ins-selectable"><i class="fa fa-times-circle"></i></span>
        </div>
        <div class="searchbox-result-wrapper ins-section-wrapper">
            <div class="ins-section-container"></div>
        </div>
    </div>
</div>
<script>
    (function (window) {
        var INSIGHT_CONFIG = {
            TRANSLATION: {
                POSTS: '文章',
                PAGES: '页面',
                CATEGORIES: '分类',
                TAGS: '标签',
                UNTITLED: '(无标题)',
            },
            CONTENT_URL: '/content.json',
        };
        window.INSIGHT_CONFIG = INSIGHT_CONFIG;
    })(window);
</script>
<script src="/js/insight.js" defer></script>
<link rel="stylesheet" href="/css/search.css">
<link rel="stylesheet" href="/css/insight.css">
    
</body>
</html>